/*
 *  Copyright 2012 Dirk Vranckaert
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package eu.vranckaert.vvl.activities.preferences.alarm;

import android.app.*;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
import eu.vranckaert.vvl.R;
import eu.vranckaert.vvl.model.TrafficInfoAlarm;
import eu.vranckaert.vvl.model.TrafficInfoGraphicalEnum;
import eu.vranckaert.vvl.model.TrafficInfoTextEnum;
import eu.vranckaert.vvl.model.TypeTrafficInfoEnum;
import eu.vranckaert.vvl.utils.context.Constants;
import eu.vranckaert.vvl.utils.context.DateUtil;
import eu.vranckaert.vvl.utils.context.Preference;
import eu.vranckaert.vvl.utils.context.StringUtil;
import eu.vranckaert.vvl.utils.view.MultiSelectSpinner;

import java.util.*;

/**
 * User: DIRK VRANCKAERT
 * Date: 28/02/12
 * Time: 8:38
 */
public class AlarmChooserActivity extends Activity {
    private static final String LOG_TAG = AlarmChooserActivity.class.getSimpleName();

    private List<Constants.WeekDays> repeatingDaysOptions;
    private List<TypeTrafficInfoEnum> typeTrafficInfoOptions;
    private List<TrafficInfoGraphicalEnum.Region> graphicalRegionOptions;
    private List<TrafficInfoTextEnum.InformationType> textInformationTypeOptions;
    private List<TrafficInfoTextEnum.Region> textRegionOptions;
    private List<TrafficInfoTextEnum.Highroad> textHighroadValues;
    private List<TrafficInfoTextEnum.SecondaryRoads> textSecondaryRoadValues;

    private Calendar selectedAlarmTime = null;
    private List<Constants.WeekDays> selectedRepeatingDays = new ArrayList<Constants.WeekDays>();
    private TypeTrafficInfoEnum selectedTypeTrafficInfo = null;
    private TrafficInfoGraphicalEnum.Region graphicalSelectedRegion = null;
    private ArrayList<TrafficInfoTextEnum.InformationType> textSelectedInformationTypes = new ArrayList<TrafficInfoTextEnum.InformationType>();
    private ArrayList<TrafficInfoTextEnum.Region> textSelectedRegions = new ArrayList<TrafficInfoTextEnum.Region>();
    private ArrayList<TrafficInfoTextEnum.Highroad> textSelectedHighroads = new ArrayList<TrafficInfoTextEnum.Highroad>();
    private ArrayList<TrafficInfoTextEnum.SecondaryRoads> textSelectedSecondaryRoads = new ArrayList<TrafficInfoTextEnum.SecondaryRoads>();

    private TextView validationError;
    
    private Button alarmTimeButton;
    private MultiSelectSpinner repeatingDaysSpinner;
    private Spinner typeTrafficInfoSpinner;
    private View graphicalCriteriaContainer;
    private Spinner graphicalCriteriaRegionSpinner;
    private View textCriteriaContainer;
    private MultiSelectSpinner textInformationSpinner;
    private MultiSelectSpinner textRegionSpinner;
    private MultiSelectSpinner textHighroadSpinner;
    private MultiSelectSpinner textSecondaryRoadSpinner;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alarm_chooser);

        loadViewObjects();
        initializeView();
        applyDefaultValues();
        attachButtons();
    }

    private void loadViewObjects() {
        validationError = (TextView) findViewById(R.id.validation);
                
        alarmTimeButton = (Button) findViewById(R.id.alarm_chooser_spinner_time_button);
        repeatingDaysSpinner = (MultiSelectSpinner) findViewById(R.id.alarm_chooser_repeating_days_spinner);

        typeTrafficInfoSpinner = (Spinner) findViewById(R.id.alarm_chooser_spinner_type_traffic_info);
        graphicalCriteriaContainer = findViewById(R.id.criteria_traffic_info_graphical_container);
        graphicalCriteriaRegionSpinner = (Spinner) findViewById(R.id.traffic_info_graphical_spinner_region);
        textCriteriaContainer = findViewById(R.id.criteria_traffic_info_text_container);
        textInformationSpinner = (MultiSelectSpinner) findViewById(R.id.traffic_info_text_spinner_information);
        textRegionSpinner = (MultiSelectSpinner) findViewById(R.id.traffic_info_text_spinner_region);
        textHighroadSpinner = (MultiSelectSpinner) findViewById(R.id.traffic_info_text_spinner_highroads);
        textSecondaryRoadSpinner = (MultiSelectSpinner) findViewById(R.id.traffic_info_text_spinner_secondary_roads);
    }

    private void initializeView() {
        //Traffic info types
        repeatingDaysOptions = Arrays.asList(Constants.WeekDays.values());
        Boolean[] defaultRepeatingDaysValues = new Boolean[repeatingDaysOptions.size()];
        for (int i=0; i< repeatingDaysOptions.size(); i++) {
            defaultRepeatingDaysValues[i] = false;
        }
        repeatingDaysSpinner.setItems(
                Arrays.asList(getResources().getStringArray(R.array.preferences_category_alarms_criteria_values_repeating_days)),
                Arrays.asList(defaultRepeatingDaysValues),
                getString(R.string.preferences_category_alarms_criteria_repeating_days_all_selected),
                getString(R.string.preferences_category_alarms_criteria_repeating_days_none_selected),
                getString(R.string.preferences_category_alarms_criteria_repeating_days_prompt),
                new MultiSelectSpinner.MultiSelectSpinnerListener() {
                    @Override
                    public void onItemsSelected(boolean[] selected) {
                        selectedRepeatingDays.clear();
                        for (int i = 0; i < selected.length; i++) {
                            if (selected[i]) {
                                selectedRepeatingDays.add(repeatingDaysOptions.get(i));
                            }
                        }
                    }
                }
        );

        //Traffic info types
        typeTrafficInfoOptions = Arrays.asList(TypeTrafficInfoEnum.values());
        ArrayAdapter<CharSequence> trafficInfoTypeAdapter = ArrayAdapter.createFromResource(this,
                R.array.preferences_category_alarms_criteria_values_type_traffic_info, android.R.layout.simple_spinner_item);
        trafficInfoTypeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        typeTrafficInfoSpinner.setAdapter(trafficInfoTypeAdapter);


        typeTrafficInfoSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                selectedTypeTrafficInfo = typeTrafficInfoOptions.get(pos);
                switch (selectedTypeTrafficInfo) {
                    case GRAPHICAL:
                        graphicalCriteriaContainer.setVisibility(View.VISIBLE);
                        textCriteriaContainer.setVisibility(View.GONE);
                        break;
                    case TEXT:
                        graphicalCriteriaContainer.setVisibility(View.GONE);
                        textCriteriaContainer.setVisibility(View.VISIBLE);
                        break;
                }
            }

            public void onNothingSelected(AdapterView<?> adapterView) {
            }
        });

        //Graphical Criteria
        //Region list
        graphicalRegionOptions = Arrays.asList(TrafficInfoGraphicalEnum.Region.values());
        ArrayAdapter<CharSequence> dateRangeAdapter = ArrayAdapter.createFromResource(this,
                R.array.traffic_info_graphical_criteria_spinner_values_region, android.R.layout.simple_spinner_item);
        dateRangeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        graphicalCriteriaRegionSpinner.setAdapter(dateRangeAdapter);

        graphicalCriteriaRegionSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                graphicalSelectedRegion = graphicalRegionOptions.get(pos);
            }

            public void onNothingSelected(AdapterView<?> adapterView) {
            }
        });

        //Text Criteria
        //InformationType list
        textInformationTypeOptions = Arrays.asList(TrafficInfoTextEnum.InformationType.values());
        Boolean[] defaultInformationValues = new Boolean[textInformationTypeOptions.size()];
        for (int i=0; i< textInformationTypeOptions.size(); i++) {
            defaultInformationValues[i] = false;
        }
        textInformationSpinner.setItems(
                Arrays.asList(getResources().getStringArray(R.array.traffic_info_text_criteria_spinner_values_information)),
                Arrays.asList(defaultInformationValues),
                getString(R.string.traffic_info_text_criteria_spinner_all_selected),
                getString(R.string.traffic_info_text_criteria_spinner_none_selected),
                getString(R.string.traffic_info_text_criteria_spinner_information_prompt),
                new MultiSelectSpinner.MultiSelectSpinnerListener() {
                    @Override
                    public void onItemsSelected(boolean[] selected) {
                        textSelectedInformationTypes.clear();
                        for (int i = 0; i < selected.length; i++) {
                            if (selected[i]) {
                                textSelectedInformationTypes.add(textInformationTypeOptions.get(i));
                            }
                        }
                    }
                }
        );

        //Region list
        textRegionOptions = Arrays.asList(TrafficInfoTextEnum.Region.values());
        Boolean[] defaultRegionValues = new Boolean[textRegionOptions.size()];
        for (int i=0; i< textRegionOptions.size(); i++) {
            defaultRegionValues[i] = false;
        }
        textRegionSpinner.setItems(
                Arrays.asList(getResources().getStringArray(R.array.traffic_info_text_criteria_spinner_values_region)),
                Arrays.asList(defaultRegionValues),
                getString(R.string.traffic_info_text_criteria_spinner_all_selected),
                getString(R.string.traffic_info_text_criteria_spinner_none_selected),
                getString(R.string.traffic_info_text_criteria_spinner_region_prompt),
                new MultiSelectSpinner.MultiSelectSpinnerListener() {
                    @Override
                    public void onItemsSelected(boolean[] selected) {
                        textSelectedRegions.clear();
                        for (int i = 0; i < selected.length; i++) {
                            if (selected[i]) {
                                textSelectedRegions.add(textRegionOptions.get(i));
                            }
                        }
                    }
                }
        );

        //Highroads list
        textHighroadValues = Arrays.asList(TrafficInfoTextEnum.Highroad.values());
        Boolean[] defaultHighroadValues = new Boolean[textHighroadValues.size()];
        for (int i=0; i< textHighroadValues.size(); i++) {
            defaultHighroadValues[i] = false;
        }
        textHighroadSpinner.setItems(
                Arrays.asList(getResources().getStringArray(R.array.traffic_info_text_criteria_spinner_values_highroad)),
                Arrays.asList(defaultHighroadValues),
                getString(R.string.traffic_info_text_criteria_spinner_all_selected),
                getString(R.string.traffic_info_text_criteria_spinner_none_selected),
                getString(R.string.traffic_info_text_criteria_spinner_highroads_prompt),
                new MultiSelectSpinner.MultiSelectSpinnerListener() {
                    @Override
                    public void onItemsSelected(boolean[] selected) {
                        textSelectedHighroads.clear();
                        for (int i = 0; i < selected.length; i++) {
                            if (selected[i]) {
                                textSelectedHighroads.add(textHighroadValues.get(i));
                            }
                        }
                    }
                }
        );

        //Secondary roads list
        textSecondaryRoadValues = Arrays.asList(TrafficInfoTextEnum.SecondaryRoads.values());
        Boolean[] defaultSecondaryRoadValues = new Boolean[textSecondaryRoadValues.size()];
        for (int i=0; i< textSecondaryRoadValues.size(); i++) {
            defaultSecondaryRoadValues[i] = false;
        }
        textSecondaryRoadSpinner.setItems(
                Arrays.asList(getResources().getStringArray(R.array.traffic_info_text_criteria_spinner_values_secondary_road)),
                Arrays.asList(defaultSecondaryRoadValues),
                getString(R.string.traffic_info_text_criteria_spinner_all_selected),
                getString(R.string.traffic_info_text_criteria_spinner_none_selected),
                getString(R.string.traffic_info_text_criteria_spinner_secondary_roads_prompt),
                new MultiSelectSpinner.MultiSelectSpinnerListener() {
                    @Override
                    public void onItemsSelected(boolean[] selected) {
                        textSelectedSecondaryRoads.clear();
                        for (int i = 0; i < selected.length; i++) {
                            if (selected[i]) {
                                textSelectedSecondaryRoads.add(textSecondaryRoadValues.get(i));
                            }
                        }
                    }
                }
        );
    }
    
    private void applyDefaultValues() {
        // Set the default visibility for the validation error
        validationError.setVisibility(View.GONE);

        // Set the default value for the traffic info types
        typeTrafficInfoSpinner.setSelection(0);
        selectedTypeTrafficInfo = typeTrafficInfoOptions.get(0);
        graphicalCriteriaContainer.setVisibility(View.VISIBLE);
        textCriteriaContainer.setVisibility(View.GONE);
    }

    private void attachButtons() {
        alarmTimeButton.setOnClickListener(new AlarmTimeClickListener());
    }

    private class AlarmTimeClickListener implements View.OnClickListener {
        @Override
        public void onClick(View view) {
            Calendar cal = Calendar.getInstance();
            final boolean is24HourClock = DateUtil.System.is24HourClock(AlarmChooserActivity.this);
            
            if (selectedAlarmTime != null) {
                cal = selectedAlarmTime;
            }
            
            TimePickerDialog timePickerDialog = new TimePickerDialog(
                    AlarmChooserActivity.this,
                    new TimePickerDialog.OnTimeSetListener() {
                        public void onTimeSet(TimePicker timePicker, int hourOfDay, int minute) {
                            Calendar cal = Calendar.getInstance();
                            cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
                            cal.set(Calendar.MINUTE, minute);
                            selectedAlarmTime = cal;
                            String dateString = cal.get(Calendar.HOUR) + ":" + StringUtil.leftPad("" + cal.get(Calendar.MINUTE), "0", 2);
                            if (!is24HourClock) {
                                dateString +=  " " + (cal.get(Calendar.AM_PM) == 0 ? "AM" : "PM");
                            }

                            alarmTimeButton.setText(dateString);
                        }
                    },
                    cal.get(Calendar.HOUR_OF_DAY),
                    cal.get(Calendar.MINUTE),
                    is24HourClock
            );
            timePickerDialog.setTitle(R.string.preferences_category_alarms_criteria_alarm_time_prompt);
            timePickerDialog.setOnCancelListener(new DatePickerDialog.OnCancelListener() {
                public void onCancel(DialogInterface dialogInterface) {
                    dialogInterface.cancel();
                }
            });
            timePickerDialog.show();
        }
    }

    private boolean validation() {
        boolean validData = true;
        List<Integer> validationStringIds = new ArrayList<Integer>();
        
        if (selectedAlarmTime == null) {
            validData = false;
            validationStringIds.add(R.string.preferences_category_alarms_criteria_validation_error_alarm_time);
        }
        
        switch (selectedTypeTrafficInfo) {
            case GRAPHICAL: {
                if (graphicalSelectedRegion == null) {
                    validData = false;
                    validationStringIds.add(R.string.preferences_category_alarms_criteria_validation_error_graphical_selected_region);
                }
                break;
            }
            case TEXT: {
                if (textSelectedInformationTypes == null || textSelectedInformationTypes.isEmpty()) {
                    validData = false;
                    validationStringIds.add(R.string.preferences_category_alarms_criteria_validation_error_text_selected_information_types);
                }
                if ( (textSelectedRegions == null || textSelectedRegions.isEmpty()) &&
                        (textSelectedHighroads == null || textSelectedHighroads.isEmpty()) &&
                        (textSelectedSecondaryRoads == null || textSelectedSecondaryRoads.isEmpty()) ) {
                    validData = false;
                    validationStringIds.add(R.string.preferences_category_alarms_criteria_validation_error_text_selected_regions);
                }
                break;
            }
        }
        
        if (!validData) {
            StringBuilder sb = new StringBuilder();
            sb.append(getString(R.string.preferences_category_alarms_criteria_validation_error_base) + "\n");
            for (int i=0; i<validationStringIds.size(); i++) {
                sb.append(getString(validationStringIds.get(i)));
                
                if (i < validationStringIds.size()-1) {
                    sb.append("\n");
                }
            }

            validationError.setText(sb.toString());
            validationError.setVisibility(View.VISIBLE);
        } else {
            validationError.setVisibility(View.GONE);
        }
        
        return validData;
    }
    
    public void onSaveClick(View view) {
        if (!validation()) {
            return;
        }

        TrafficInfoAlarm alarm = new TrafficInfoAlarm();
        alarm.setRepeatingDays(selectedRepeatingDays);
        alarm.setTypeTrafficInfo(selectedTypeTrafficInfo);
        alarm.setGraphicalRegion(graphicalSelectedRegion);
        alarm.setTextInfoTypes(textSelectedInformationTypes);
        alarm.setTextRegions(textSelectedRegions);
        alarm.setTextHighroads(textSelectedHighroads);
        alarm.setTextSecondaryRoads(textSelectedSecondaryRoads);

        if (selectedAlarmTime.before(Calendar.getInstance())) {
            selectedAlarmTime.add(Calendar.DAY_OF_MONTH, 1);
        }
        alarm.setAlarmTime(selectedAlarmTime);

        List<Integer> alarmIds = new ArrayList<Integer>();
        if (selectedRepeatingDays == null || selectedRepeatingDays.isEmpty()) {
            alarmIds.add(Preference.getNextAlarmRequestCode(AlarmChooserActivity.this));
        } else {
            for (Constants.WeekDays weekDay : selectedRepeatingDays) {
                alarmIds.add(Preference.getNextAlarmRequestCode(AlarmChooserActivity.this));
            }
        }
        alarm.setAlarmIds(alarmIds);
        
        Preference.addAlarm(AlarmChooserActivity.this, alarm);

        Intent startAlarmsIntent = new Intent("eu.vranckaert.vvl.launchAllAlarms");
        sendBroadcast(startAlarmsIntent);

        finish();
    }
}